package service;

import common.Message;
import common.MessageType;
import common.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 余一
 * @date 2021/10/30  11:44
 */
public class QQServer {

    private ServerSocket serverSocket;

    //创建一个集合，存放多个用户，如果是这些用户登录，就认为是合法
    private static ConcurrentHashMap<String,User> validUser = new ConcurrentHashMap<>();

    static {
        validUser.put("欧文",new User("欧文","123"));
        validUser.put("哈登",new User("哈登","222"));
        validUser.put("杜兰特",new User("杜兰特","333"));
    }



    /**
     * 判断用户账号密码是否正确
     * @param userId
     * @param password
     * @return
     */
    private boolean checkUser(String userId,String password){
        User user = validUser.get(userId);
        if (user == null) {
            return false;
        }
        if (!user.getPassword().equals(password)) {
            return false;
        }
        return true;
    }

    /**
     * 判断用户是否存在
     * @param userId
     * @return
     */
    public static boolean checkUser(String userId){
        User user = validUser.get(userId);
        if (user == null) {
            return false;
        }
        return true;
    }

    public QQServer(){
        try {
            System.out.println("服务端正在监听9999端口...");
            serverSocket = new ServerSocket(9999);
            NewsServiceThread newsServiceThread = new NewsServiceThread();
            new Thread(newsServiceThread).start();
            //循环监听客户端
            while (true){
                Socket socket = serverSocket.accept();
                //读取客户端发送的user数据
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                User user = (User) objectInputStream.readObject();
                //验证该用户的帐号密码
                Message message = new Message();
                if (this.checkUser(user.getUserId(),user.getPassword())) {
                    //帐号密码正确
                    message.setMesType(MessageType.MESSAGE_LOGIN_SUCCESS);
                    //响应数据给客户端
                    objectOutputStream.writeObject(message);
                    //创建一个线程，和该客户端保持通信
                    ServerClientThread serverClientThread = new ServerClientThread(user.getUserId(), socket);
                    serverClientThread.start();
                    //将该线程放入集合容器进行管理
                    ThreadManager.addThread(user.getUserId(),serverClientThread);

                    //判断该用户是否有离线消息
                    ConcurrentHashMap<String, ArrayList<Message>> db =
                            OfflineMessageThreadManager.getDb();
                    if (!db.isEmpty()){
                            db.forEach((userId,messages) -> {
                                //有离线消息，转发给该用户
                                if (user.getUserId().equals(userId)){
                                    messages.forEach(msg ->{
                                        try {
                                            OutputStream outputStream = ThreadManager.getThread(userId).getSocket().getOutputStream();
                                            ObjectOutputStream oos = new ObjectOutputStream(outputStream);
                                            oos.writeObject(msg);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    });
                                    //发送完成后删除这个用户的离线消息
                                    OfflineMessageThreadManager.deleteOfflineMessage(userId);
                                }
                            });
                    }

                    //判断该用户是否有离线文件消息
                    ConcurrentHashMap<String, ArrayList<Message>> fileDb =
                            OfflineFilesThreadManager.getDb();
                    if (!fileDb.isEmpty()){
                        fileDb.forEach((userId,messages) -> {
                                //有离线消息，转发给该用户
                                if (user.getUserId().equals(userId)){
                                    messages.forEach(msg ->{
                                        try {
                                            OutputStream outputStream = ThreadManager.getThread(userId).getSocket().getOutputStream();
                                            ObjectOutputStream oos = new ObjectOutputStream(outputStream);
                                            oos.writeObject(msg);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    });
                                    //发送完成后删除这个用户的离线消息
                                    OfflineMessageThreadManager.deleteOfflineMessage(userId);
                                }
                            });
                    }
                } else {
                    message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                    objectOutputStream.writeObject(message);
                    socket.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
